const multer = require('multer');
const path = require('path');
const fs = require('fs-extra');
const Model3D = require('../models/modelModel');
const fileUtils = require('../utils/fileUtils');
const config = require('../config/config');

// 配置multer存储
const storage = multer.diskStorage({
    destination: async function (req, file, cb) {
        try {
            // 确保目录存在
            const storagePath = await fileUtils.ensureStorageDir(req.userId, req.params.modelId);
            cb(null, storagePath);
        } catch (error) {
            cb(error);
        }
    },
    filename: function (req, file, cb) {
        // 构建文件名：模型ID + 时间戳 + 原始扩展名
        const fileExt = path.extname(file.originalname);
        const fileName = `${req.params.modelId}_${Date.now()}${fileExt}`;
        cb(null, fileName);
    }
});

// 文件过滤器
const fileFilter = (req, file, cb) => {
    if (!fileUtils.isValidModelFormat(file.originalname)) {
        return cb(new Error('不支持的文件格式，仅支持 GLB/OBJ/STL 格式'), false);
    }
    cb(null, true);
};

// 创建multer上传实例
const upload = multer({
    storage: storage,
    fileFilter: fileFilter,
    limits: {
        fileSize: 100 * 1024 * 1024 // 限制100MB
    }
}).single('file');

// 纹理文件存储设置
const textureStorage = multer.diskStorage({
    destination: async function (req, file, cb) {
        try {
            // 确保目录存在
            const storagePath = await fileUtils.ensureStorageDir(req.userId, req.params.modelId);
            const texturePath = path.join(storagePath, 'textures');
            await fs.ensureDir(texturePath);
            cb(null, texturePath);
        } catch (error) {
            cb(error);
        }
    },
    filename: function (req, file, cb) {
        // 构建文件名：模型ID + 描述 + 时间戳 + 原始扩展名
        const textureType = req.body.textureType || 'color';
        const fileExt = path.extname(file.originalname);
        const fileName = `${req.params.modelId}_${textureType}_${Date.now()}${fileExt}`;
        cb(null, fileName);
    }
});

// 纹理文件过滤器
const textureFileFilter = (req, file, cb) => {
    const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
    if (!allowedTypes.includes(file.mimetype)) {
        return cb(new Error('不支持的文件格式，仅支持JPEG/PNG/WEBP格式'), false);
    }
    cb(null, true);
};

// 创建multer上传实例
const uploadTexture = multer({
    storage: textureStorage,
    fileFilter: textureFileFilter,
    limits: {
        fileSize: 20 * 1024 * 1024 // 限制20MB
    }
}).single('texture');

/**
 * 上传模型文件
 */
exports.uploadModelFile = async (req, res) => {
    try {
        // 验证模型存在且属于当前用户
        const model = await Model3D.findOne({ _id: req.params.modelId, userId: req.userId });
        if (!model) {
            return res.status(404).json({
                status: 404,
                message: '模型不存在或无权访问'
            });
        }

        // 处理文件上传
        upload(req, res, async function (err) {
            if (err) {
                return res.status(400).json({
                    status: 400,
                    message: err.message
                });
            }

            if (!req.file) {
                return res.status(400).json({
                    status: 400,
                    message: '未检测到上传文件'
                });
            }

            try {
                // 如果已有旧文件，删除它
                if (model.file && model.file.filePath) {
                    await fileUtils.deleteFile(model.file.filePath);
                }

                // 生成缩略图
                const thumbnailPath = path.join(
                    path.dirname(req.file.path),
                    `${path.basename(req.file.path, path.extname(req.file.path))}_thumbnail.png`
                );

                const base64Thumbnail = await fileUtils.generateThumbnail(req.file.path, thumbnailPath);

                // 更新模型文件信息
                model.file = {
                    originalName: req.file.originalname,
                    fileName: req.file.filename,
                    fileSize: req.file.size,
                    fileType: fileUtils.getFileExtension(req.file.originalname),
                    filePath: req.file.path,
                    uploadDate: new Date()
                };

                // 设置模型几何体类型为外部导入模型
                if (!model.geometry || !model.geometry.type) {
                    model.geometry = {
                        type: 'external_model',
                        // 保留默认位置、旋转和缩放
                        position: { x: 0, y: 0, z: 0 },
                        rotation: { x: 0, y: 0, z: 0 },
                        scale: { x: 1, y: 1, z: 1 },
                        color: '#FFFFFF',
                        material: {
                            type: 'standard',
                            wireframe: false,
                            metalness: 0.1,
                            roughness: 0.5,
                            opacity: 1.0,
                            transparent: false
                        }
                    };
                } else if (model.geometry.type !== 'external_model') {
                    // 如果已有几何体但不是external_model类型，更新为external_model
                    model.geometry.type = 'external_model';
                }

                // 更新缩略图信息
                model.thumbnail = {
                    path: thumbnailPath,
                    base64: base64Thumbnail,
                    generateDate: new Date()
                };

                await model.save();

                return res.json({
                    status: 200,
                    data: {
                        fileId: model._id,
                        fileSize: `${(req.file.size / (1024 * 1024)).toFixed(2)}MB`
                    }
                });
            } catch (error) {
                console.error('处理上传文件错误:', error);
                return res.status(500).json({
                    status: 500,
                    message: '服务器处理文件时出错'
                });
            }
        });
    } catch (error) {
        console.error('上传模型文件错误:', error);
        return res.status(500).json({
            status: 500,
            message: '服务器错误'
        });
    }
};

/**
 * 下载模型文件
 */
exports.downloadModelFile = async (req, res) => {
    try {
        // 获取请求的格式参数
        const requestedFormat = req.query.format ? req.query.format.toLowerCase() : null;

        // 验证格式参数
        if (requestedFormat && !config.storage.allowedFormats.includes(requestedFormat)) {
            return res.status(400).json({
                status: 400,
                message: '不支持的文件格式，仅支持 glb/obj/stl 格式'
            });
        }

        // 验证模型存在且属于当前用户
        const model = await Model3D.findOne({ _id: req.params.modelId, userId: req.userId });
        if (!model) {
            return res.status(404).json({
                status: 404,
                message: '模型不存在或无权访问'
            });
        }

        // 检查模型是否有关联文件
        if (!model.file || !model.file.filePath) {
            return res.status(404).json({
                status: 404,
                message: '该模型没有关联文件'
            });
        }

        // 检查文件是否存在
        if (!await fs.pathExists(model.file.filePath)) {
            return res.status(404).json({
                status: 404,
                message: '文件不存在或已被删除'
            });
        }

        // 如果请求的格式与当前文件格式不同且有指定格式，需要进行格式转换
        // 注意：实际项目中，这里应该实现模型格式转换逻辑
        // 这里简化处理，直接返回现有文件

        // 设置文件名
        const filename = requestedFormat
            ? `${model.name}.${requestedFormat}`
            : model.file.originalName || `model.${model.file.fileType}`;

        // 设置响应头
        res.setHeader('Content-Disposition', `attachment; filename="${encodeURIComponent(filename)}"`);
        res.setHeader('Content-Type', 'application/octet-stream');

        // 发送文件
        return res.sendFile(model.file.filePath, { root: '/' });

    } catch (error) {
        console.error('下载模型文件错误:', error);
        return res.status(500).json({
            status: 500,
            message: '服务器错误'
        });
    }
};

/**
 * 获取模型缩略图
 */
exports.getModelThumbnail = async (req, res) => {
    try {
        // 验证模型存在且属于当前用户
        const model = await Model3D.findOne({ _id: req.params.modelId, userId: req.userId });
        if (!model) {
            return res.status(404).json({
                status: 404,
                message: '模型不存在或无权访问'
            });
        }

        // 检查模型是否有缩略图
        if (!model.thumbnail || !model.thumbnail.base64) {
            return res.status(404).json({
                status: 404,
                message: '该模型没有缩略图'
            });
        }

        return res.json({
            status: 200,
            data: {
                thumbnail: model.thumbnail.base64
            }
        });

    } catch (error) {
        console.error('获取模型缩略图错误:', error);
        return res.status(500).json({
            status: 500,
            message: '服务器错误'
        });
    }
};

/**
 * 上传纹理贴图
 */
exports.uploadTextureFile = async (req, res) => {
    try {
        // 验证模型存在且属于当前用户
        const model = await Model3D.findOne({ _id: req.params.modelId, userId: req.userId });
        if (!model) {
            return res.status(404).json({
                status: 404,
                message: '模型不存在或无权访问'
            });
        }

        // 处理文件上传
        uploadTexture(req, res, async function (err) {
            if (err) {
                return res.status(400).json({
                    status: 400,
                    message: err.message
                });
            }

            if (!req.file) {
                return res.status(400).json({
                    status: 400,
                    message: '未检测到上传文件'
                });
            }

            try {
                const textureType = req.body.textureType || 'color';
                const textureMapping = req.body.mapping || 'standard';

                // 检查现有的几何体数据
                if (!model.geometry || !model.geometry.material) {
                    // 如果模型没有材质信息，创建一个基础材质
                    if (!model.geometry) {
                        model.geometry = {
                            type: model.geometry ? model.geometry.type : 'custom',
                            material: {}
                        };
                    } else if (!model.geometry.material) {
                        model.geometry.material = {};
                    }
                }

                // 更新材质信息以包含纹理路径
                if (!model.geometry.material.textures) {
                    model.geometry.material.textures = {};
                }

                // 存储纹理信息
                model.geometry.material.textures[textureType] = {
                    path: req.file.path,
                    originalName: req.file.originalname,
                    fileName: req.file.filename,
                    fileSize: req.file.size,
                    mapping: textureMapping,
                    uploadDate: new Date()
                };

                // 如果是颜色纹理，设置材质类型为标准材质
                if (textureType === 'color') {
                    model.geometry.material.type = model.geometry.material.type || 'standard';
                }

                // 如果是透明度纹理，设置透明属性
                if (textureType === 'alpha' || textureType === 'opacity') {
                    model.geometry.material.transparent = true;
                }

                await model.save();

                return res.json({
                    status: 200,
                    data: {
                        textureId: model._id,
                        textureType,
                        fileName: req.file.filename,
                        fileSize: `${(req.file.size / (1024 * 1024)).toFixed(2)}MB`
                    },
                    message: '纹理上传成功'
                });
            } catch (error) {
                console.error('处理纹理文件错误:', error);
                return res.status(500).json({
                    status: 500,
                    message: '服务器处理文件时出错'
                });
            }
        });
    } catch (error) {
        console.error('上传纹理文件错误:', error);
        return res.status(500).json({
            status: 500,
            message: '服务器错误'
        });
    }
};

/**
 * 创建并上传外部模型
 * 一步完成创建模型和上传文件
 */
exports.createAndUploadExternalModel = async (req, res) => {
    try {
        // 处理文件上传
        upload(req, res, async function (err) {
            if (err) {
                return res.status(400).json({
                    status: 400,
                    message: err.message
                });
            }

            if (!req.file) {
                return res.status(400).json({
                    status: 400,
                    message: '未检测到上传文件'
                });
            }

            try {
                // 从请求体中获取模型信息
                const modelData = JSON.parse(req.body.modelData || '{}');

                // 验证必填字段
                if (!modelData.name) {
                    // 如果没有提供名称，使用文件名
                    modelData.name = path.basename(req.file.originalname, path.extname(req.file.originalname));
                }

                // 创建新模型
                const newModel = new Model3D({
                    name: modelData.name,
                    description: modelData.description || `导入的外部模型文件`,
                    userId: req.userId,
                    geometry: {
                        type: 'external_model',
                        color: modelData.color || '#FFFFFF',
                        position: modelData.position || { x: 0, y: 0, z: 0 },
                        rotation: modelData.rotation || { x: 0, y: 0, z: 0 },
                        scale: modelData.scale || { x: 1, y: 1, z: 1 },
                        material: modelData.material || {
                            type: 'standard',
                            wireframe: false,
                            metalness: 0.1,
                            roughness: 0.5,
                            opacity: 1.0,
                            transparent: false
                        }
                    }
                });

                // 保存模型以获取ID
                const savedModel = await newModel.save();
                const modelId = savedModel._id.toString();

                // 移动上传的文件到新模型的目录
                const storagePath = await fileUtils.ensureStorageDir(req.userId, modelId);
                const fileExt = path.extname(req.file.originalname);
                const fileName = `${modelId}_${Date.now()}${fileExt}`;
                const newFilePath = path.join(storagePath, fileName);

                // 移动文件
                await fs.move(req.file.path, newFilePath);

                // 生成缩略图
                const thumbnailPath = path.join(
                    storagePath,
                    `${path.basename(fileName, fileExt)}_thumbnail.png`
                );

                const base64Thumbnail = await fileUtils.generateThumbnail(newFilePath, thumbnailPath);

                // 更新模型文件信息
                savedModel.file = {
                    originalName: req.file.originalname,
                    fileName: fileName,
                    fileSize: req.file.size,
                    fileType: fileUtils.getFileExtension(req.file.originalname),
                    filePath: newFilePath,
                    uploadDate: new Date()
                };

                // 更新缩略图信息
                savedModel.thumbnail = {
                    path: thumbnailPath,
                    base64: base64Thumbnail,
                    generateDate: new Date()
                };

                await savedModel.save();

                return res.status(201).json({
                    status: 201,
                    data: {
                        model: {
                            id: savedModel._id.toString(),
                            name: savedModel.name,
                            description: savedModel.description,
                            thumbnail: savedModel.thumbnail?.base64,
                            fileSize: `${(req.file.size / (1024 * 1024)).toFixed(2)}MB`
                        },
                        message: '外部模型创建并上传成功'
                    }
                });
            } catch (error) {
                console.error('创建并上传外部模型错误:', error);
                return res.status(500).json({
                    status: 500,
                    message: '服务器处理文件时出错: ' + error.message
                });
            }
        });
    } catch (error) {
        console.error('创建并上传外部模型错误:', error);
        return res.status(500).json({
            status: 500,
            message: '服务器错误'
        });
    }
}; 